/*
 * Copyright 2011 Dominik Pretzsch <dominik.pretzsch at gmail.com>.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package de.blacksheep.jmoteextract.archive.strategy;

import de.blacksheep.jmoteextract.archive.callback.ArchiveOpenVolumeCallback;
import java.io.File;
import java.io.FileNotFoundException;
import java.util.logging.Level;
import java.util.logging.Logger;
import net.sf.sevenzipjbinding.ArchiveFormat;
import net.sf.sevenzipjbinding.IInStream;
import net.sf.sevenzipjbinding.ISevenZipInArchive;
import net.sf.sevenzipjbinding.SevenZip;
import net.sf.sevenzipjbinding.SevenZipException;

/**
 * <code>ArchiveOpenStrategyMultipartRar</code> provides a strategy to <br>
 * open multi-part archives of RAR type. <br>
 * 
 * @author Dominik Pretzsch <dominik.pretzsch at gmail.com>
 */
public class ArchiveOpenStrategyMultipartRar implements ArchiveOpenStrategy {
    
    private ISevenZipInArchive inArchive;    
    private static final Logger LOGGER =  Logger.getLogger(ArchiveOpenStrategyMultipartRar.class.getName());

    public ISevenZipInArchive open(File file) 
            throws SevenZipException, FileNotFoundException {
        
        LOGGER.log(Level.FINE, "Try to open with {0}", this.getClass().getName());
        
        ArchiveOpenVolumeCallback archiveOpenVolumeCallback;
        archiveOpenVolumeCallback = new ArchiveOpenVolumeCallback();
        
        String firstVol = getFirstVolume(file.getAbsolutePath());
        LOGGER.log(Level.FINE, "Detected first volume: {0}", firstVol);
        
        LOGGER.log(Level.FINE, "Try to getStream");
        IInStream inStream = archiveOpenVolumeCallback.getStream(firstVol);
        
        LOGGER.log(Level.FINE, "Try to openInArchive");
        inArchive = SevenZip.openInArchive(ArchiveFormat.RAR, 
                                           inStream, 
                                           archiveOpenVolumeCallback);
        
        LOGGER.log(Level.FINE, "Returning inArchive");
        return inArchive;
    }

    public void close() throws SevenZipException {
        LOGGER.log(Level.FINE, "Try to close archive");
        inArchive.close();
    }
    
    protected boolean isFirstVolume(String path) {
        return path.matches(".*\\.part[0]*?1\\.rar$");
    }
    
    protected String getFirstVolume(String path) {
        if (!isFirstVolume(path)) {
            // ..\multi-part[.]part101.rar
            int iPart = path.lastIndexOf(".part");
            // ..\multi-part.part101[.]rar
            int iExt  = path.lastIndexOf(".rar");
            // ..\multi-part.part[101].rar
            String volNum = path.substring(iPart + 5, iExt);
            // Create format string. Ex: 101 -> "%02d"
            String format = String.format("%%0%dd", volNum.length());
            // Reformat. Ex: 101 -> 001
            String firstVolNum = String.format(format, 1);
            // Prepare new part name. Ex: ".part001.rar"
            String newPartName = ".part" + firstVolNum + ".rar";
            // Cut off old part name
            path = path.substring(0, iPart);
            // Concat new part name
            path = path.concat(newPartName);
        }        
        return path;
    }
}
